package com.wkbb.sports.controller;

import com.alibaba.excel.EasyExcel;
import com.wkbb.common.constants.ErrorCode;
import com.wkbb.common.constants.VersionConstant;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.utils.ExcelUtil;
import com.wkbb.common.utils.ListUtil;
import com.wkbb.common.utils.ObjectUtil;
import com.wkbb.common.utils.ThreadPoolUtil;
import com.wkbb.sports.dto.AchievementDto;
import com.wkbb.sports.dto.AchievementExcelDto;
import com.wkbb.sports.dto.AchievementPageDto;
import com.wkbb.sports.dto.AchievementProjectItemDto;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.service.AchievementService;
import com.wkbb.sports.thread.AchievementScoreImportTask;
import com.wkbb.sports.thread.AchievementScoreTermTask;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RejectedExecutionException;

@RestController
@Api(description = "学生成绩管理")
@RequestMapping("/sports/{apiVersion}/achievement")
@Slf4j
public class AchievementController {

    @Autowired
    private AchievementService achievementService;

    @Autowired
    private BasicFeignService basicFeignService;

    @ApiOperation(value = "查询学生成绩分页列表")
    @RequestMapping(value = "/getAchievementPageList", method = RequestMethod.GET)
    public ResultDTO<AchievementPageDto> getAchievementPageList(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "类型(1体测成绩 2技能成绩)", required = true) @RequestParam(name = "type", required = true) Integer type,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId,
            @ApiParam(value = "年级ID", required = false) @RequestParam(name = "gradeId", required = false) Long gradeId,
            @ApiParam(value = "班级ID", required = false) @RequestParam(name = "classId", required = false) Long classId,
            @ApiParam(value = "性别", required = false) @RequestParam(name = "sex", required = false) Integer sex,
            @ApiParam(value = "页码", required = true, defaultValue = "1") @RequestParam(name = "pageNo", required = true, defaultValue = "1") Integer pageNo,
            @ApiParam(value = "每页条数", required = true, defaultValue = "10") @RequestParam(name = "pageSize", required = true, defaultValue = "10") Integer pageSize)
    {
        log.info("getAchievementPageList orgId:{} termId:{} gradeId:{} pageNo:{} pageSize:{}",orgId,termId,gradeId,pageNo,pageSize);
        
        try {

            AchievementPageDto achievementPageDto = achievementService.getAchievementPageList(type,orgId,termId,gradeId,classId,sex,pageNo,pageSize);

            return new ResultDTO<AchievementPageDto>(achievementPageDto);

        } catch (Exception e) {
            log.error("***********AchievementController.getAchievementPageList******", e);
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "查询成绩")
    @RequestMapping(value = "/getAchievement", method = RequestMethod.GET)
    public ResultDTO<AchievementDto> getAchievement(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "类型(1体测成绩 2技能成绩)", required = true) @RequestParam(name = "type", required = true) Integer type,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId,
            @ApiParam(value = "用户ID", required = true) @RequestParam(name = "userId", required = true) Long userId)
    {
        log.info("updateAchievement type:{} orgId:{} termId:{} userId:{}",type,orgId,termId,userId);

        try {

            if(null==type||null==orgId||null==termId||null==userId)
            {
                return new ResultDTO<>(ErrorCode.PARAM_MISSING);
            }

            AchievementDto achievementDto = achievementService.getAchievement(type,orgId,termId,userId);

            return new ResultDTO<AchievementDto>(achievementDto);

        } catch (Exception e) {
            log.error("***********AchievementController.getAchievement******", e);
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "修改成绩")
    @RequestMapping(value = "/updateAchievement", method = RequestMethod.GET)
    public ResultDTO updateAchievement(
            @ApiParam(value = "接口版本", required = true, defaultValue = VersionConstant.V1) @PathVariable(value = "apiVersion", required = true) String apiVersion,
            @RequestBody AchievementDto achievementDto)
    {
        log.info("updateAchievement achievementDto:{}",achievementDto);

        try {

            if(null==achievementDto.getOrgId()||null==achievementDto.getTermId()||null==achievementDto.getUserId())
            {
                return new ResultDTO<>(ErrorCode.PARAM_MISSING);
            }

            achievementService.updateAchievement(achievementDto);

            return new ResultDTO<AchievementPageDto>(true);

        } catch (Exception e) {
            log.error("***********AchievementController.getExaminePageList******", e);
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "上传学生体育成绩")
    @RequestMapping(value = "/uploadAchievementExcel", method = RequestMethod.POST)
    public ResultDTO uploadAchievementExcel(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId,
            @ApiParam(value = "成绩类型(1体测2技能)", required = true) @RequestParam(name = "type", required = true) Integer type,
            @ApiParam(value = "文件", required = true) @RequestParam("uploadFile") MultipartFile uploadFile)
    {
        try {
            log.info("***********uploadAchievementExcel******orgId:{}", orgId);

            if(null==orgId || null==termId || null==type){
                return new ResultDTO<>(ErrorCode.PARAM_MISSING);
            }

            InputStream in = null;
            try {

                if (null == uploadFile) {
                    log.error("---uploadAchievementExcel---文件不存在！");
                    return new ResultDTO(ErrorCode.BUSINESS_DATA_WRONG);
                }

                Integer columns = 19;//30列
                in = uploadFile.getInputStream();
                List<Object> excelData = EasyExcel.read(in).sheet().headRowNumber(0).doReadSync();
                List<Object> titleDataList = null;
                List<Object> scoreDataList = null;
                if (!excelData.isEmpty()) {
                    titleDataList = excelData.subList(0,1);
                    scoreDataList = excelData.subList(1,excelData.size());
                    List<Object[]> titleList = ObjectUtil.trans(titleDataList,columns);
                    List<Object[]> data = ObjectUtil.trans(scoreDataList,columns);
                    log.info("***********数据处理开始******orgId:{}", orgId);
                    //数据处理
                    Integer total = data.size();
                    Integer pageSize = 50;
                    Integer pages = (total + pageSize - 1) / pageSize;

                    //获取线程池
                    ExecutorService executorService = ThreadPoolUtil.getExecutorService();
                    FutureTask<ResultDTO> future;
                    Integer currentRow = 0;
                    for (int currentPage = 1; currentPage <= pages; currentPage++) {
                        List<Object[]> dataList = ListUtil.pager(currentPage,pageSize,data);
                        currentRow = (currentPage - 1) * pageSize + 1;
                        future = new FutureTask<ResultDTO>(new AchievementScoreImportTask(achievementService,basicFeignService,type,orgId,termId,titleList,dataList,currentRow));
                        executorService.execute(future);
                    }

                    log.info("***********数据处理结束******orgId:{}", orgId);
                }
                return new ResultDTO(true);
            }catch (RejectedExecutionException e) {
                log.error("----已达到线程池最大等待队列---",e);
                return new ResultDTO(ErrorCode.SYSTEM_THREAD_MAXQUEUE);
            } catch (Exception e) {
                log.error("----uploadAchievementExcel----", e);
                return new ResultDTO(ErrorCode.SYSTEM_EXCEPTION);
            } finally {
                if (null != in) {
                    try {
                        in.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            log.error("***********uploadAchievementExcel******", e);
            return new ResultDTO<>(false);
        }
    }

    @ApiOperation(value = "下载成绩模板")
    @RequestMapping(value = "/downloadAchievementTmeplateExcel", method = RequestMethod.GET)
    public ResultDTO downloadAchievementTmeplateExcel(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "成绩类型(1体测2技能)", required = true) @RequestParam(name = "type", required = true) Integer type,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId,
            @ApiParam(value = "年级ID", required = true) @RequestParam(name = "gradeId", required = true) Long gradeId,
            @ApiParam(value = "班级ID", required = false) @RequestParam(name = "classId", required = false) Long classId,
            @ApiParam(value = "性别", required = false) @RequestParam(name = "sex", required = false) Integer sex,
            HttpServletResponse response)
    {
        try
        {
            AchievementExcelDto achievementExcelPageDto = achievementService.downloadAchievementTmeplateExcel(type, orgId, termId, gradeId, classId, sex);
            String[] headerList = achievementExcelPageDto.getHeaderList().toArray(new String[]{});
            List<AchievementDto> dataList = achievementExcelPageDto.getDataList();
            List<Object[]> infoList = new ArrayList<>();
            if(!dataList.isEmpty())
            {
                dataList.forEach(e -> {
                    Object[] d = new Object[headerList.length];
                    int i = 0;
                    d[i++] = e.getGradeName();
                    d[i++] = e.getClassName();
                    d[i++] = e.getUserName();
                    d[i++] = e.getStrSex();
                    d[i++] = e.getUserNo();
                    List<AchievementProjectItemDto> projectList = e.getAchievementList();
                    for(AchievementProjectItemDto projectItemDto : projectList)
                    {
                        d[i++] = projectItemDto.getAchievement();
                    }
                    infoList.add(d);
                });
            }

            log.info("infoList:{}",infoList.size());

            ExcelUtil.exportAttendExcel("sheet1", "学生成绩列表模板", headerList, infoList, response);
        }
        catch (Exception e) {
            log.error("***********downloadStudentScoreExcel******", e);
        }

        return null;
    }

    @ApiOperation(value = "下载成绩")
    @RequestMapping(value = "/downloadAchievementExcel", method = RequestMethod.GET)
    public ResultDTO downloadAchievementExcel(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "成绩类型(1体测2技能)", required = true) @RequestParam(name = "type", required = true) Integer type,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId,
            @ApiParam(value = "年级ID", required = true) @RequestParam(name = "gradeId", required = true) Long gradeId,
            @ApiParam(value = "班级ID", required = false) @RequestParam(name = "classId", required = false) Long classId,
            @ApiParam(value = "性别", required = false) @RequestParam(name = "sex", required = false) Integer sex,
            HttpServletResponse response)
    {
        try
        {
            AchievementExcelDto achievementExcelDto = achievementService.downloadAchievementExcel(type, orgId, termId, gradeId, classId, sex);
            String[] headerList = achievementExcelDto.getHeaderList().toArray(new String[]{});
            List<AchievementDto> dataList = achievementExcelDto.getDataList();
            List<Object[]> infoList = new ArrayList<>();
            if(!dataList.isEmpty())
            {
                for(AchievementDto achievementDto : dataList)
                {
                    Object[] d = new Object[headerList.length];
                    int i = 0;
                    d[i++] = achievementDto.getGradeName();
                    d[i++] = achievementDto.getClassName();
                    d[i++] = achievementDto.getUserName();
                    d[i++] = achievementDto.getStrSex();
                    d[i++] = achievementDto.getUserNo();
                    List<AchievementProjectItemDto> projectList = achievementDto.getAchievementList();
                    for(AchievementProjectItemDto projectItemDto : projectList)
                    {
                        d[i++] = projectItemDto.getAchievement();
                    }
                    infoList.add(d);
                }
            }

            String title = "成绩列表";
            if(null!=achievementExcelDto && null!=achievementExcelDto.getTerm())
            {
                title = achievementExcelDto.getTerm().getName() + "成绩列表";
            }

            ExcelUtil.exportAttendExcel("sheet1", title, headerList, infoList, response);
        }
        catch (Exception e) {
            log.error("***********downloadAchievementExcel******", e);
        }

        return null;
    }

    @ApiOperation(value = "按学期计算学生成绩")
    @RequestMapping(value = "/doTermAchievementScore", method = RequestMethod.GET)
    public ResultDTO doTermAchievementScore(
            @ApiParam(value = "接口版本", defaultValue = VersionConstant.V1, required = true) @PathVariable(name = "apiVersion", required = true) String apiVersion,
            @ApiParam(value = "组织ID", required = true) @RequestParam(name = "orgId", required = true) Long orgId,
            @ApiParam(value = "考期ID", required = true) @RequestParam(name = "termId", required = true) Long termId)
    {
        try
        {

            //异步处理
            AchievementScoreTermTask achievementScoreTermTask = new AchievementScoreTermTask(achievementService,orgId,termId);

            ThreadPoolUtil.addPoolTask(achievementScoreTermTask);

            return new ResultDTO<>(true);
        }
        catch (Exception e) {
            log.error("***********downloadStudentScoreExcel******", e);
            return new ResultDTO<>(false);
        }
    }
}
